
import javax.swing.JFrame;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.sql.Blob;
import javax.swing.JOptionPane;

/**
 *
 * @author Andy
 */
public class Controller {

	JFrame frame;
	JFrame pframe;
	Login login;
	FriendsList friendsList;
	UserProfile userProfile;
	FriendProfile friendProfile;
	DatabaseConnection dbConnect;
	ProfilePictureUploader profilePictureUploader;
	String username, email, description;
	GamePreface gamePreface;
	Game game;
	boolean picUploader;

	public Controller() {
		//To change the window that comes up initially, pass a different
		//JPane object to frame.add() below

		frame = new JFrame("Draw Something");
		// smithre5: This doesn't allow for saving in the middle of anything, but.
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		dbConnect = new DatabaseConnection();
		login = new Login(this, dbConnect);
		userProfile = new UserProfile(this, dbConnect);
		friendProfile = new FriendProfile(this, dbConnect);
		friendsList = new FriendsList(this, dbConnect);
		friendsList = new FriendsList(this, dbConnect);
		gamePreface = new GamePreface(this, dbConnect);
		game = new Game(this, dbConnect);
		frame.add(login);                                    //THIS LINE
		frame.setSize(new Dimension(720, 650));
		frame.setVisible(true);
		picUploader = false;
	}

	public void enterProgram(String username, String email, String description, Blob pic) {
		this.username = username;
		this.description = description;
		this.email = email;
		frame.getContentPane().removeAll();
		userProfile.setUsername(this.username);
		userProfile.setEmail(this.email);
		userProfile.setDescription(this.description);
		userProfile.updateGamesList();
		userProfile.updateStats();
		try {
			userProfile.setProfilePicture(pic);
		} catch (SQLException ex) {
			System.out.println("Profile picture not read from database.");
		}
		frame.add(userProfile);
		frame.getContentPane().validate();
		frame.getContentPane().repaint();
	}

	public void openFriendsList() {
		frame.getContentPane().removeAll();
		friendsList.addFriends();
		frame.add(friendsList);
		frame.getContentPane().validate();
		frame.getContentPane().repaint();
		frame.setSize(new Dimension(900, 700));
	}

	public void openFriendProfile(String username) {
		frame.getContentPane().removeAll();
		frame.setSize(new Dimension(720, 650));
		friendProfile.getInformation(username);
		friendProfile.updateStats();
		frame.add(friendProfile);
		frame.getContentPane().validate();
		frame.getContentPane().repaint();
	}

	public void openProfile() {
		if (!this.username.equals("") && this.username != null) {
			frame.setSize(new Dimension(720, 650));
			frame.getContentPane().removeAll();
			userProfile.updateGamesList();
			userProfile.updateStats();
			frame.add(userProfile);
			frame.getContentPane().validate();
			frame.getContentPane().repaint();
		}
	}

	public void openGame(String opponent) {
		// smithre5: This is quickly growing into a mess of hodge-podge bits for testing.
		// Check if user already has a game in progress.
		String checkGameFmt =
				"SELECT state AS state FROM game_state WHERE user1 = '%s' AND user2 = '%s'";
		String checkGame1 = String.format(checkGameFmt, this.username, opponent);
		String checkGame2 = String.format(checkGameFmt, opponent, this.username);


		boolean hasGame = false;
		boolean firstPlayer = false;

		try {
			dbConnect.connect();
			ResultSet checkGameRes = dbConnect.executeQuery(checkGame1);


			if (checkGameRes != null && checkGameRes.next()) {
				hasGame = true;
				firstPlayer = true;
			} else {
				checkGameRes = dbConnect.executeQuery(checkGame2);
				if (checkGameRes != null && checkGameRes.next()) {
					hasGame = true;
				}
			}


			if (!hasGame) {
				frame.getContentPane().removeAll();
				frame.setSize(new Dimension(720, 650));
				game.create(username, opponent);
				game.getGuessPanel().setState("select");
				gamePreface.getNewWords();
				frame.add(gamePreface);
				frame.getContentPane().validate();
				frame.getContentPane().repaint();
			} else {
				String checkPlayerTurn = String.format(
						"SELECT player, state, word, value FROM game_state WHERE user1='%s' AND user2='%s'",
						firstPlayer ? this.username : opponent,
						firstPlayer ? opponent : this.username);

				ResultSet checkPlayerTurnRes = dbConnect.executeQuery(checkPlayerTurn);
				if (checkPlayerTurnRes != null) {
					try {
						checkPlayerTurnRes.first();

						if ((firstPlayer && checkPlayerTurnRes.getInt(1) != 1)
								|| (!firstPlayer && checkPlayerTurnRes.getInt(1) != 2)) {
							JOptionPane.showMessageDialog(frame, "Wait your turn!");
							game.clearImage();
							game.setDrawing(false);
						} else if (checkPlayerTurnRes.getString("state").equals("select")) {
							frame.getContentPane().removeAll();
							frame.setSize(new Dimension(720, 650));

							// game setup
							game.setFirstPlayer(firstPlayer);
							game.setLocalPlayer(username);
							game.setRemotePlayer(opponent);
							game.setWord(null);
							game.setValue(0);

							// image setup
							game.getGuessPanel().setState("select");
							game.clearImage();
							game.setDrawing(true);

							gamePreface.getNewWords();

							frame.add(gamePreface);
							frame.getContentPane().validate();
							frame.getContentPane().repaint();
						} else {
							frame.getContentPane().removeAll();
							frame.setSize(new Dimension(720, 650));

							// game setup
							game.setFirstPlayer(firstPlayer);
							game.setLocalPlayer(username);
							game.setRemotePlayer(opponent);
							String word = checkPlayerTurnRes.getString("word");
							game.setWord(word);
							game.setValue(checkPlayerTurnRes.getInt("value"));

							// image setup
							if (checkPlayerTurnRes.getString("state").equals("guess")) { // guess
								game.getGuessPanel().setState("guess");
								game.clearImage();
								game.setDrawing(false);
								game.loadImage(word);
							} else { // draw
								game.getGuessPanel().setState("draw");
								game.clearImage();
								game.setDrawing(true);
							}

							frame.add(game);
							frame.getContentPane().validate();
							frame.getContentPane().repaint();
						}
					} catch (SQLException e) {
						// TODO Handle failure.
						System.err.println(
								"ERR: Controller.openGame: failed to check player turn: " + e.getLocalizedMessage());

						return;
					} finally {
						checkPlayerTurnRes.close();
					}
				}
			}

			dbConnect.closeConnection();
		} catch (SQLException e) {
			System.err.println("Failed requesting if user has game: " + e.getLocalizedMessage());
		}
	}

	public void openPictureUploader(String username) {
		if (!picUploader) {
			pframe = new JFrame("Choose New Picture");
			profilePictureUploader = new ProfilePictureUploader(this, dbConnect, pframe);
			pframe.setSize(new Dimension(525, 400));
			profilePictureUploader.setUsername(username);
			pframe.add(profilePictureUploader);
			pframe.setVisible(true);
			myFrameListener listen = new myFrameListener();
			pframe.addWindowListener(listen);
		}
	}

	public void closeProfilePictureUploader() {
		picUploader = false;
		WindowEvent wev = new WindowEvent(pframe, WindowEvent.WINDOW_CLOSING);
		Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
	}

	public static void main(String[] argv) {
		Controller controller = new Controller();
	}

	private class myFrameListener implements WindowListener {

		public void windowActivated(WindowEvent arg0) {
		}

		public void windowClosed(WindowEvent arg0) {
		}

		public void windowClosing(WindowEvent arg0) {
			picUploader = false;
		}

		public void windowDeactivated(WindowEvent arg0) {
		}

		public void windowDeiconified(WindowEvent arg0) {
		}

		public void windowIconified(WindowEvent arg0) {
		}

		public void windowOpened(WindowEvent arg0) {
		}
	}
}
